#include "FileReader.h"

FileReader::FileReader(string f){
	int fileType;
	FileName=f;
	DataFile.open(FileName.c_str());
	if(!DataFile.is_open()){
		throw(EXC_FILE_NOT_FOUND);
	}
	DataFile.close();

	fileType=getFileType();
	
	switch(fileType){
		case FILE_TYPE_LECROY:
			readLecroy();
		break;
		case FILE_TYPE_AGILENT:
			readAgilent();
		break;
		default:
			throw(EXC_FILE_FORMAT_INVALID);
	}
}
FileReader::~FileReader(){
	unsigned int i,j;
	
	if(DataFile!=NULL){
		DataFile.close();
	}
	for(i=0;i<Tracks.size();i++){
		//cout <<i<<endl;
		if(Tracks[i]==NULL){
			continue;
		}
		for(j=i+1;j<Tracks.size();j++){
			if(Tracks[j]==Tracks[i]){
				Tracks[j]=NULL;
			}
		}
		//cout <<"d "<<i<<endl;
		delete Tracks[i];
	}

}
uint32_t FileReader::getNSample(){
	return NSample;
}
char FileReader::getFormatType(){
	return FormatType;
}
unsigned int FileReader::getFormatSize(){
	return FormatSize;
}
vector<float*> FileReader::getTracks(){
	return Tracks;
}
char FileReader::getFileType()
{
	DataFile.open(FileName.c_str());
	try{
		if(isLecroy()){
			DataFile.close();
			return FILE_TYPE_LECROY;
		}
	}catch(int e){};
	DataFile.close();
	
	DataFile.open(FileName.c_str());
	try{
		if(isAgilent()){
			DataFile.close();
			return FILE_TYPE_AGILENT;//*CARLO*
		}
	}catch(exception e){};
	DataFile.close();
	
	return 0;
}
bool FileReader::isLecroy(){
	char buf[100];
	string buf_s;
	unsigned int p1,p2;
	
	DataFile.read(buf,100);
	buf_s.assign((char*)buf,100);
	p1=buf_s.find("WAVEDESC");
	if(p1==buf_s.npos){
		return 0;
	}
	p2=buf_s.find("LECROY");
	if(p2-p1!=16 || p1==buf_s.npos){
		return 0;
	}
	return 1;
}
//*CARLO* implementato controllo semplice per vedere se file è Agilent
bool FileReader::isAgilent(){
	char id[2];
	string buf_s;
	
	DataFile.read(id,2);
	buf_s.assign((char*)id,2);
	
	if(buf_s.compare("AG")==0){
		return 1;
	}
	return 0; //+++
}
void FileReader::readLecroy(){
	char buf[344];
	string buf_s;
	int p1;
	uint16_t temp16_1,temp16_2,temp16_3;
	float* Track;
	unsigned int file_size,data_start;
	
	DataFile.open(FileName.c_str());
	DataFile.seekg (0, ios::end);
	file_size = DataFile.tellg();
	if(file_size<344){
		throw(EXC_FILE_FORMAT_INVALID);
	}
	DataFile.seekg (0, ios::beg);
	DataFile.read(buf,344);
	
	buf_s.assign((char*)buf,344);
	p1=buf_s.find("WAVEDESC");
	if(p1==-1){
		throw(EXC_FILE_FORMAT_INVALID);
	}
	memcpy(&temp16_1,&buf[p1+32],2);
	if(temp16_1==0){
		FormatType='b';
		FormatSize=1;
	}else if(temp16_1==1){
		FormatType='c';//+++ formati specificati nel file Matlab
		FormatSize=2;
	}else{
		throw(EXC_FILE_FORMAT_INVALID);
	}
	memcpy(&temp16_1,&buf[p1+36],2);
	memcpy(&temp16_2,&buf[p1+40],2);
	memcpy(&temp16_3,&buf[p1+48],2);
	data_start=p1+temp16_1+temp16_2+temp16_3;
	if(data_start>file_size){
		throw(EXC_FILE_FORMAT_INVALID);
	}
	
	Track = new float[file_size-data_start];
	DataFile.seekg (data_start, ios::beg);
	DataFile.read((char *)Track,file_size-data_start);
	NSample=(file_size-data_start)/FormatSize;
	cout<<"formato LeCroy!!"<<endl;
	//cout<<NSample<<endl;
	Tracks.push_back(Track);
}
void FileReader::readAgilent(){
  
	AgilentFileHeader fileHeader;
	uint8_t* Track;
	float* Traccia;
	int j;

	//*CARLO* devo leggere prima l'intestazione (header)
	DataFile.open(FileName.c_str());
	DataFile.seekg (0, ios::beg); //mi porto all'inizio del file
	DataFile.read(fileHeader.cookie,2);
	DataFile.read(fileHeader.version,2);
	DataFile.read((char*) &fileHeader.fileSize,sizeof(int));
	DataFile.read((char*) &fileHeader.numberOfWaveforms,sizeof(int));
	
//	cout<<fileHeader.cookie<<"."<<fileHeader.version<<"."<<fileHeader.fileSize<<"."
//	<<fileHeader.numberOfWaveforms<<endl;

	for (j=0;j < fileHeader.numberOfWaveforms;j++)
            {	
		//*CARLO* ora leggo l'intestazione dell'onda per ogni onda	
		AgilentWaveformHeader waveHeader;
		DataFile.read((char*)&waveHeader.HeaderSize,sizeof(int));
		DataFile.read((char*)&waveHeader.WaveformType,sizeof(int));
		DataFile.read((char*)&waveHeader.NWaveformBuffers,sizeof(int));
		DataFile.read((char*)&waveHeader.Points,sizeof(int));
		DataFile.read((char*)&waveHeader.Count,sizeof(int));
		DataFile.read((char*)&waveHeader.XDisplayRange,sizeof(float));
		DataFile.read((char*)&waveHeader.XDisplayOrigin,sizeof(double));
		DataFile.read((char*)&waveHeader.XIncrement,sizeof(double));
		DataFile.read((char*)&waveHeader.XOrigin,sizeof(double));
		DataFile.read((char*)&waveHeader.XUnits,sizeof(int));
		DataFile.read((char*)&waveHeader.YUnits,sizeof(int));
		DataFile.read(waveHeader.Date,16);
		DataFile.read(waveHeader.Time,16);
		DataFile.read(waveHeader.Frame,24);
		DataFile.read(waveHeader.WaveformLabel,16);
		DataFile.read((char*)&waveHeader.TimeTag,sizeof(double));
		DataFile.read((char*)&waveHeader.SegmentIndex,sizeof(int));
/*
		cout<<waveHeader.HeaderSize<<"."<<waveHeader.WaveformType<<"."<<waveHeader.NWaveformBuffers<<"."
		<<waveHeader.Points<<"."<<waveHeader.XDisplayRange<<"."<<waveHeader.XDisplayOrigin<<"."
		<<waveHeader.XIncrement<<"."<<waveHeader.XOrigin<<"."<<waveHeader.XUnits<<"."
		<<waveHeader.YUnits<<"."<<waveHeader.Date<<"."<<waveHeader.Time<<"."
		<<waveHeader.Frame<<"."<<waveHeader.WaveformLabel<<"."<<waveHeader.TimeTag<<"."
		<<waveHeader.SegmentIndex<<"."<<endl;
*/		
		//*CARLO* ora leggo l'intestazione DATI dell'onda per ogni onda
		AgilentWaveformDataHeader waveDataHeader;
		DataFile.read((char*)&waveDataHeader.HeaderSize,sizeof(int));
		DataFile.read((char*)&waveDataHeader.BufferType,sizeof(short));
		DataFile.read((char*)&waveDataHeader.BytesPerPoint,sizeof(short));
		DataFile.read((char*)&waveDataHeader.BufferSize,sizeof(int));		
/*		
		cout<<waveDataHeader.HeaderSize<<"."<<waveDataHeader.BufferType<<"."<<waveDataHeader.BytesPerPoint<<"."
		<<waveDataHeader.BufferSize<<"."<<endl;
*/		
		Traccia= new float[waveDataHeader.BufferSize];	
		Track = new uint8_t[waveDataHeader.BufferSize];
		NSample=waveHeader.Points; //*CARLO* Occhio! così salva i campioni dell'ultima traccia letta, i file che abbiamo hanno solo una traccia
		FormatSize=sizeof(float); //*CARLO* temporanea
		FormatType='f';//*CARLO* temporanea 
		DataFile.read((char *)Traccia,waveDataHeader.BufferSize);
		Tracks.push_back(Traccia);
            }

	cout<<"formato Agilent!!"<<endl;
	//+++
}
//+++ _little_-big, agilent, multi lecroy,int8/int16 in lecroy
//+++ real sample - nsample



